package com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.geeguo.ebuilder.core.common.model.vo.PageListVO;
import com.geeguo.ebuilder.core.common.utils.GsonUtils;
import com.geeguo.ebuilder.core.common.utils.ObjectEqualsHelper;
import com.geeguo.ebuilder.core.common.utils.PageUtils;
import com.geeguo.ebuilder.core.common.utils.SqlHelper;
import com.geeguo.ebuilder.core.redis.constants.CacheTimeConstants;
import com.geeguo.ebuilder.core.redis.service.RedisCacheService;
import com.geeguo.ebuilder.operation.base.redis.utils.CacheKeyFactory;
import com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.mapper.DataSourceInfoMapper;
import com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.model.DataSourceInfoConverter;
import com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.model.DataSourceInfoEntity;
import com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.model.DataSourceInfoQuery;
import com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.model.DataSourceInfoCO;
import com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.model.DataSourceInfoVO;
import com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.producer.DataSourceInfoMQProducer;
import com.geeguo.ebuilder.operation.business.tenant.datasourceinfo.service.DataSourceInfoService;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Slf4j
@Service
public class DataSourceInfoServiceImpl implements DataSourceInfoService {

    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private DataSourceInfoMapper dataSourceInfoMapper;
    @Autowired
    private DataSourceInfoMQProducer dataSourceInfoMQProducer;

    @Override
    public PageListVO<DataSourceInfoVO> list(DataSourceInfoQuery query) {
        Map<String, Object> params = new HashMap<>();
        if (StringUtils.isNotEmpty(query.getName())) {
            params.put("name", SqlHelper.getFullImplict(query.getName()));
        }
        if (StringUtils.isNotEmpty(query.getHost())) {
            params.put("host", SqlHelper.getFullImplict(query.getHost()));
        }
        if (StringUtils.isNotEmpty(query.getDbName())) {
            params.put("dbName", SqlHelper.getFullImplict(query.getDbName()));
        }
        IPage<DataSourceInfoEntity> page = dataSourceInfoMapper.list(new Page<>(query.getPageNo(), query.getPageSize()), params);
        List<DataSourceInfoVO> result = new ArrayList<>();
        if (page.getRecords() != null && !page.getRecords().isEmpty()) {
            for (DataSourceInfoEntity item : page.getRecords()) {
                result.add(DataSourceInfoConverter.INSTANCE.convert2VO(item));
            }
        }
        return PageUtils.getPageListVO(page, result);
    }

    @Override
    public List<DataSourceInfoVO> listAll() {
        List<DataSourceInfoEntity> data = dataSourceInfoMapper.selectList(null);
        List<DataSourceInfoVO> result = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(data)) {
            for (DataSourceInfoEntity entity : data) {
                result.add(DataSourceInfoConverter.INSTANCE.convert2VO(entity));
            }
        }
        return result;
    }

    @Override
    public DataSourceInfoVO get(String id) {
        DataSourceInfoEntity result = dataSourceInfoMapper.selectById(id);
        if (result != null) {
            return DataSourceInfoConverter.INSTANCE.convert2VO(result);
        }
        return null;
    }

    @Override
    public DataSourceInfoCO getCached(String id) {
        DataSourceInfoCO result = null;
        String cacheKey = CacheKeyFactory.INSTANCE.getDataSourceInfo(id);
        String cacheJson = redisCacheService.get(cacheKey);
        if (StringUtils.isNotEmpty(cacheJson)) {
            result = GsonUtils.fromJson(cacheJson, DataSourceInfoCO.class);
        }
        if (result == null) {
            DataSourceInfoEntity entity = dataSourceInfoMapper.selectById(id);
            if (entity != null) {
                result = DataSourceInfoConverter.INSTANCE.convert2CO(entity);
                cacheJson = GsonUtils.toJson(result);
                redisCacheService.set(cacheKey, cacheJson, CacheTimeConstants.CACHE_WEEK);
            }
        }
        return result;
    }
    
    @Override
    public boolean save(DataSourceInfoEntity entity) {
        return dataSourceInfoMapper.insert(entity) > 0;
    }
    
    @Override
    public boolean update(DataSourceInfoEntity current, DataSourceInfoEntity old) {
        Map<String, Object> changeValues = ObjectEqualsHelper.equals(current, old, new String[] {"name", "host", "port", "dbName", "username", "password", "initialSize", "minIdle", "maxActive"});
        if (changeValues.isEmpty()) {
            return true;
        } else {
            changeValues.put("id", current.getId());
            changeValues.put("modifyTime", current.getModifyTime());
            changeValues.put("modifyUser", current.getModifyUser());
            boolean result = dataSourceInfoMapper.updateByParams(changeValues) == 1;
            if (result) {
                removeCached(current.getId());
                dataSourceInfoMQProducer.sendChangeMessage(current.getId());
            }
            return result;
        }
    }
    
    @Override
    public boolean remove(String id) {
        boolean result = dataSourceInfoMapper.deleteById(id) == 1;
        if (result) {
            removeCached(id);
            dataSourceInfoMQProducer.sendChangeMessage(id);
        }
        return result;
    }

    private void removeCached(String id) {
        String cacheKey = CacheKeyFactory.INSTANCE.getDataSourceInfo(id);
        redisCacheService.del(cacheKey);
    }
}
